package com.frank.framework.util;

import java.time.Duration;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
/**
 * 对 Redis 5种数据结构进一步封装操作
 * 1. String 可以是字符串、整数或者浮点数
 * 2. List 一个链表，链表上的每个节点都包含了一个字符串
 * 3. Set 包含字符串的无序集合，并且被包含的每个字符串都是独一无二的、各不相同
 * 4. Hash 包含键值对的无序散列表
 * 5. Zset 字符串成员与浮点数分值之间的有序映射，元素的排列顺序由分值的大小决定
 *
 */
@Component
@ConditionalOnProperty(value = "spring.redis.enabled", havingValue = "true")
public class RedisUtil extends CachingConfigurerSupport{

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public StringRedisTemplate getStringRedisTemplate() {
        return stringRedisTemplate;
    }
    // ==================== key 常用相关操作 ==================== //

    /**
     * 【Key】 删除 key
     * @param key 键
     * @return 成功删除存在的key时为 true
     */
    public Boolean delete(String key) {
        return stringRedisTemplate.delete(key);
    }
    /**
     * 【Key】 批量删除 key
     * @param keys 键
     * @return 返回成功删除的数量
     */
    public Long delete(Collection<String> keys) {
        return stringRedisTemplate.delete(keys);
    }
    /**
     * 【Key】 序列化 key
     * @param key 键
     * @return 返回字节
     */
    public byte[] dump(String key) {
        return stringRedisTemplate.dump(key);
    }
    /**
     * 【Key】 是否存在 key
     * @return 返回布尔值
     */
    public Boolean hasKey(String key) {
        return stringRedisTemplate.hasKey(key);
    }
    /**
     * 【Key】 设置 key 过期时间
     * @param key
     * @param timeout
     * @param unit 时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES 秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     * @return 返回布尔值
     */
    public Boolean expire(String key, long timeout, TimeUnit unit) {
        return stringRedisTemplate.expire(key, timeout, unit);
    }
    /**
     * 【Key】 设置 key 过期时间
     * @param key
     * @param date
     * @return
     */
    public Boolean expireAt(String key, Date date) {
        return stringRedisTemplate.expireAt(key, date);
    }
    /**
     * 【Key】 获取 key 的剩余过期时间
     * @param key
     * @param timeUnit
     * @return
     */
    public Long getExpire(String key, TimeUnit timeUnit) {
        return stringRedisTemplate.getExpire(key, timeUnit);
    }
    /**
     * 【Key】 获取 key 的剩余过期时间
     * @param key
     * @return
     */
    public Long getExpire(String key) {
        return stringRedisTemplate.getExpire(key);
    }
    /**
     * 【Key】 移除 key 的过期时间， key 将不会过期
     * @param key
     * @return
     */
    public Boolean persist(String key) {
        return stringRedisTemplate.persist(key);
    }
    /**
     * 【Key】 查找匹配的 key
     * @param pattern
     * @return
     */
    public Set<String> keys(String pattern) {
        return stringRedisTemplate.keys(pattern);
    }
    /**
     * 【Key】 将当前 Redis 数据库分片中的 key 移到指定的数据库分片中
     * @param key
     * @param dbIndex Redis 数据库分片索引
     * @return
     */
    public Boolean move(String key, int dbIndex) {
        return stringRedisTemplate.move(key, dbIndex);
    }
    /**
     * 【Key】 从当前 Redis 数据库分片中随机返回一个 key
     * @return
     */
    public String randomKey() {
        return stringRedisTemplate.randomKey();
    }
    /**
     * 【Key】 重命名 key 的名称
     * @param oldKey 当前 key 名称
     * @param newKey 新的 key 名称
     */
    public void rename(String oldKey, String newKey) {
        stringRedisTemplate.rename(oldKey, newKey);
    }
    /**
     * 【Key】 仅当 newKey 不存在时，将 oldKey 重命名为 newKey
     * @param oldKey
     * @param newKey
     * @return
     */
    public Boolean renameIfAbsent(String oldKey, String newKey) {
        return stringRedisTemplate.renameIfAbsent(oldKey, newKey);
    }
    /**
     * 【Key】 返回 key 所储存的值的类型
     * @param key
     * @return
     */
    public DataType type(String key) {
        return stringRedisTemplate.type(key);
    }
    // ==================== String 常用相关操作 ==================== //
    /**
     * 【String】 设置指定 key 的值
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }
    /**
     * 【String】 只有在 key 不存在时才设置 key 的值
     * @param key
     * @param value
     */
    public Boolean setIfAbsent(String key, String value) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value);
    }
    /**
     * 【String】 设置指定 key 的值，并指定过期时间
     * @param key
     * @param value
     * @param timeout
     */
    public void set(String key, String value, Duration timeout) {
        stringRedisTemplate.opsForValue().set(key, value, timeout);
    }
    /**
     * 【String】 只有在 key 不存在时才设置 key 的值，并指定过期时间
     * @param key
     * @param value
     * @param timeout
     */
    public Boolean setIfAbsent(String key, String value, Duration timeout) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value, timeout);
    }
    /**
     * 【String】 设置指定 key 的值，并指定过期时间
     * @param key
     * @param value
     * @param timeout
     * @param unit 时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES 秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     */
    public void set(String key, String value, long timeout, TimeUnit unit) {
        stringRedisTemplate.opsForValue().set(key, value, timeout, unit);
    }
    /**
     * 【String】 只有在 key 不存在时才设置 key 的值，并指定过期时间
     * @param key
     * @param value
     * @param timeout
     * @param unit
     */
    public Boolean setIfAbsent(String key, String value, long timeout, TimeUnit unit) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit);
    }
    /**
     * 【String】 批量设置 key-value 对
     * @param map
     */
    public void multiSet(Map<String, String> map) {
        stringRedisTemplate.opsForValue().multiSet(map);
    }
    /**
     * 【String】 批量设置一个或多个 key-value 对，当且仅当所有给定 key 都不存在
     * @param map
     */
    public Boolean multiSetIfAbsent(Map<String, String> map) {
        return stringRedisTemplate.opsForValue().multiSetIfAbsent(map);
    }
    /**
     * 【String】 获取 key 的长度
     * @param key
     * @return
     */
    public Long size(String key) {
        return stringRedisTemplate.opsForValue().size(key);
    }
    /**
     * 【String】 增加(自增长), 负数则为自减
     * @param key
     * @param delta
     * @return 返回自增或自减后的值
     */
    public Long increment(String key, long delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }
    /**
     * 【String】 增加(自增长), 负数则为自减
     * @param key
     * @param delta
     * @return 返回自增或自减后的值
     */
    public Double increment(String key, double delta) {
        return stringRedisTemplate.opsForValue().increment(key, delta);
    }
    /**
     * 【String】 追加值到末尾
     * @param key
     * @param value
     * @return
     */
    public Integer append(String key, String value) {
        return stringRedisTemplate.opsForValue().append(key, value);
    }
    /**
     * 【String】 获取指定 key 的值
     * @param key
     * @return
     */
    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }
    /**
     * 【String】 返回存储在字符串值的子串key，由偏移确定start和end（两者都包括）
     * 0表示第一个字符，1表示第二个字符，-1表示最后一个字符，-2表示倒数第二个字符，依此类推
     * @param key
     * @param start
     * @param end
     * @return
     */
    public String get(String key, long start, long end) {
        return stringRedisTemplate.opsForValue().get(key, start, end);
    }
    /**
     * 【String】 设置key到value，并返回 key 的旧值
     * @param key
     * @param value
     * @return
     */
    public String getAndSet(String key, String value) {
        return stringRedisTemplate.opsForValue().getAndSet(key, value);
    }
    /**
     * 【String】 批量获取 key 的值
     * @param keys
     * @return
     */
    public List<String> multiGet(Collection<String> keys) {
        return stringRedisTemplate.opsForValue().multiGet(keys);
    }
    // ==================== List 常用相关操作 ==================== //
    /**
     * 【List】 获取 key 的 index 索引的值
     * @param key
     * @param index
     * @return
     */
    public String lIndex(String key, long index) {
        return stringRedisTemplate.opsForList().index(key, index);
    }
    /**
     * 【List】 获取 key 列表指定范围内的值
     * @param key
     * @param start 开始位置，0表示第一位
     * @param end 结束位置，-1表示最后一位
     * @return
     */
    public List<String> lRange(String key, long start, long end) {
        return stringRedisTemplate.opsForList().range(key, start, end);
    }
    /**
     * 【List】 将一个值插入到列表头部
     * @param key
     * @param value
     * @return 返回列表的长度
     */
    public Long lLeftPush(String key, String value) {
        return stringRedisTemplate.opsForList().leftPush(key, value);
    }
    /**
     * 【List】 在 key 列表中的指定的值（pivot）的前一位添加指定的值（value），仅当 pivot 存在时有效
     * @param key
     * @param pivot
     * @param value
     * @return 返回列表的长度
     */
    public Long lLeftPush(String key, String pivot, String value) {
        return stringRedisTemplate.opsForList().leftPush(key, pivot, value);
    }
    /**
     * 【List】 将一个或多个值插入到列表头部
     * @param key
     * @param values
     * @return 返回列表的长度
     */
    public Long lLeftPushAll(String key, String... values) {
        return stringRedisTemplate.opsForList().leftPushAll(key, values);
    }
    /**
     * 【List】 将一个或多个值插入到列表头部
     * @param key
     * @param values
     * @return 返回列表的长度
     */
    public Long lLeftPushAll(String key, Collection<String> values) {
        return stringRedisTemplate.opsForList().leftPushAll(key, values);
    }
    /**
     * 【List】 仅当 key 列表存在的时候才添加值到列表头部
     * @param key
     * @param value
     * @return 返回列表的长度
     */
    public Long leftPushIfPresent(String key, String value) {
        return stringRedisTemplate.opsForList().leftPushIfPresent(key, value);
    }
    /**
     * 【List】 将一个值添加到列表尾部
     * @param key
     * @param value
     * @return 返回列表的长度
     */
    public Long lRightPush(String key, String value) {
        return stringRedisTemplate.opsForList().rightPush(key, value);
    }
    /**
     *  【List】 在 key 列表中的指定的值（pivot）的后一位添加指定的值（value），仅当 pivot 存在时有效
     * @param key
     * @param pivot
     * @param value
     * @return 返回列表的长度
     */
    public Long lRightPush(String key, String pivot, String value) {
        return stringRedisTemplate.opsForList().rightPush(key, pivot, value);
    }
    /**
     * 【List】 将一个或多个值插入到列表尾部
     * @param key
     * @param values
     * @return 返回列表的长度
     */
    public Long lRightPushAll(String key, String... values) {
        return stringRedisTemplate.opsForList().rightPushAll(key, values);
    }
    /**
     * 【List】 将一个或多个值插入到列表尾部
     * @param key
     * @param values
     * @return 返回列表的长度
     */
    public Long lRightPushAll(String key, Collection<String> values) {
        return stringRedisTemplate.opsForList().rightPushAll(key, values);
    }
    /**
     * 【List】 仅当 key 列表存在的时候才添加值到列表尾部
     * @param key
     * @param value
     * @return 返回列表的长度
     */
    public Long lRightPushIfPresent(String key, String value) {
        return stringRedisTemplate.opsForList().rightPushIfPresent(key, value);
    }
    /**
     * 【List】 设置 key 列表的index索引上的值
     * @param key
     * @param index 索引
     * @param value
     */
    public void lSet(String key, long index, String value) {
        stringRedisTemplate.opsForList().set(key, index, value);
    }
    /**
     * 【List】 移除并获取列表第一个元素
     * @param key
     * @return
     */
    public String lLeftPop(String key) {
        return stringRedisTemplate.opsForList().leftPop(key);
    }
    /**
     * 【List】 移出并获取列表的第一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     * @param key
     * @param timeout 时间
     * @param unit 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES 秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     * @return
     */
    public String lLeftPop(String key, long timeout, TimeUnit unit) {
        return stringRedisTemplate.opsForList().leftPop(key, timeout, unit);
    }
    /**
     * 【List】 移除并获取列表最后一个元素
     * @param key
     * @return
     */
    public String lRightPop(String key) {
        return stringRedisTemplate.opsForList().rightPop(key);
    }
    /**
     * 【List】 移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     * @param key
     * @param timeout 时间
     * @param unit 时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES 秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     * @return
     */
    public String lRightPop(String key, long timeout, TimeUnit unit) {
        return stringRedisTemplate.opsForList().rightPop(key, timeout, unit);
    }
    /**
     * 【List】 从 sourcekey 的列表中删除最后一个元素，将其附加到 destinationkey 的列表中并返回其值。
     * @return
     */
    public String lRightPopAndLeftPush(String sourceKey, String destinationKey) {
        return stringRedisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey);
    }
    /**
     * 【List】 从列表中弹出一个值，将弹出的元素插入到另外一个列表中并返回它； 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
     * @param sourceKey
     * @param destinationKey
     * @param timeout
     * @param unit 时间单位, 天:TimeUnit.DAYS 小时:TimeUnit.HOURS 分钟:TimeUnit.MINUTES 秒:TimeUnit.SECONDS 毫秒:TimeUnit.MILLISECONDS
     * @return
     */
    public String lRightPopAndLeftPush(String sourceKey, String destinationKey, long timeout, TimeUnit unit) {
        return stringRedisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey, timeout, unit);
    }
    /**
     * 【List】 从存储在键中的列表中删除等于值的元素的第一个计数事件。
     * count > 0：从头不开始删除 count 个值等于 value 的元素
     * count < 0：从尾部开始删除 count 个值等于 value 的元素
     * count = 0：删除等于value的所有元素。
     * @param key
     * @param count
     * @param value
     * @return
     */
    public Long lRemove(String key, long count, Object value) {
        return stringRedisTemplate.opsForList().remove(key, count, value);
    }
    /**
     * 【List】 裁剪 list, 范围从索引0开始，都是包含关系
     * @param key
     * @param start
     * @param end
     */
    public void lTrim(String key, long start, long end) {
        stringRedisTemplate.opsForList().trim(key, start, end);
    }
    /**
     * 【List】 获取列表的长度
     * @param key
     * @return
     */
    public Long lSize(String key) {
        return stringRedisTemplate.opsForList().size(key);
    }
    // ==================== Set 常用相关操作 ==================== //
    /**
     * 【Set】 添加元素
     * @param key
     * @param values
     * @return 返回值成功添加元素的个数
     */
    public Long sAdd(String key, String... values) {
        return stringRedisTemplate.opsForSet().add(key, values);
    }
    /**
     * 【Set】 移除元素
     * @param key
     * @param values
     * @return 返回值成功移除元素的个数
     */
    public Long sRemove(String key, Object... values) {
        return stringRedisTemplate.opsForSet().remove(key, values);
    }
    /**
     * 【Set】 移除set集合中的一个随机元素并返回该元素
     * @param key
     * @return 返回被移除的随机元素
     */
    public String sPop(String key) {
        return stringRedisTemplate.opsForSet().pop(key);
    }
    /**
     * 【Set】 将value值从一个集合移动到另一个集合
     * @param key
     * @param value
     * @param destKey
     * @return
     */
    public Boolean sMove(String key, String value, String destKey) {
        return stringRedisTemplate.opsForSet().move(key, value, destKey);
    }
    /**
     * 【Set】 获取集合的大小
     * @param key
     * @return
     */
    public Long sSize(String key) {
        return stringRedisTemplate.opsForSet().size(key);
    }
    /**
     * 【Set】 判断集合是否包含value
     * @param key
     * @param value
     * @return
     */
    public Boolean sIsMember(String key, Object value) {
        return stringRedisTemplate.opsForSet().isMember(key, value);
    }
    /**
     * 【Set】 获取两个集合的交集
     * @param key
     * @param otherKey
     * @return
     */
    public Set<String> sIntersect(String key, String otherKey){
        return stringRedisTemplate.opsForSet().intersect(key, otherKey);
    }
    /**
     * 【Set】 获取key集合与多个集合的交集
     * @param key
     * @param otherKeys
     * @return
     */
    public Set<String> sIntersect(String key, Collection<String> otherKeys) {
        return stringRedisTemplate.opsForSet().intersect(key, otherKeys);
    }
    /**
     * 【Set】key集合与otherKey集合的交集存储到destKey集合中
     * @param key
     * @param otherKey
     * @param destKey
     * @return
     */
    public Long sIntersectAndStore(String key, String otherKey, String destKey) {
        return stringRedisTemplate.opsForSet().intersectAndStore(key, otherKey, destKey);
    }
    /**
     * 【Set】 key集合与多个集合的交集存储到destKey集合中
     * @param key
     * @param otherKeys
     * @param destKey
     * @return
     */
    public Long sIntersectAndStore(String key, Collection<String> otherKeys,String destKey) {
        return stringRedisTemplate.opsForSet().intersectAndStore(key, otherKeys, destKey);
    }
    /**
     * 【Set】 获取两个集合的并集
     * @param key
     * @param otherKeys
     * @return
     */
    public Set<String> sUnion(String key, String otherKeys) {
        return stringRedisTemplate.opsForSet().union(key, otherKeys);
    }
    /**
     * 【Set】 获取key集合与多个集合的并集
     * @param key
     * @param otherKeys
     * @return
     */
    public Set<String> sUnion(String key, Collection<String> otherKeys) {
        return stringRedisTemplate.opsForSet().union(key, otherKeys);
    }
    /**
     * 【Set】 key集合与otherKey集合的并集存储到destKey中
     * @param key
     * @param otherKey
     * @param destKey
     * @return
     */
    public Long sUnionAndStore(String key, String otherKey, String destKey) {
        return stringRedisTemplate.opsForSet().unionAndStore(key, otherKey, destKey);
    }
    /**
     * 【Set】key集合与多个集合的并集存储到destKey中
     * @param key
     * @param otherKeys
     * @param destKey
     * @return
     */
    public Long sUnionAndStore(String key, Collection<String> otherKeys,String destKey) {
        return stringRedisTemplate.opsForSet().unionAndStore(key, otherKeys, destKey);
    }
    /**
     * 【Set】获取两个集合的差集
     * @param key
     * @param otherKey
     * @return
     */
    public Set<String> sDifference(String key, String otherKey) {
        return stringRedisTemplate.opsForSet().difference(key, otherKey);
    }
    /**
     * 【Set】 获取key集合与多个集合的差集
     * @param key
     * @param otherKeys
     * @return
     */
    public Set<String> sDifference(String key, Collection<String> otherKeys) {
        return stringRedisTemplate.opsForSet().difference(key, otherKeys);
    }
    /**
     * 【Set】 key集合与otherKey集合的差集存储到destKey中
     * @param key
     * @param otherKey
     * @param destKey
     * @return
     */
    public Long sDifferenceAndStore(String key, String otherKey, String destKey) {
        return stringRedisTemplate.opsForSet().differenceAndStore(key, otherKey,destKey);
    }
    /**
     * 【Set】 key集合与多个集合的差集存储到destKey中
     * @param key
     * @param otherKeys
     * @param destKey
     * @return
     */
    public Long sDifferenceAndStore(String key, Collection<String> otherKeys,String destKey) {
        return stringRedisTemplate.opsForSet().differenceAndStore(key, otherKeys,destKey);
    }
    /**
     * 【Set】 获取集合所有元素
     * @param key
     * @return
     */
    public Set<String> sMembers(String key) {
        return stringRedisTemplate.opsForSet().members(key);
    }
    /**
     * 【Set】 随机获取集合中的一个元素
     * @param key
     * @return
     */
    public String sRandomMember(String key) {
        return stringRedisTemplate.opsForSet().randomMember(key);
    }
    /**
     * 【Set】 随机获取集合中的一个元素
     * @param key
     * @return
     */
    public List<String> sRandomMembers(String key, long count) {
        return stringRedisTemplate.opsForSet().randomMembers(key, count);
    }
    /**
     * 【Set】 随机获取集合中count个元素并且去除重复的
     * @param key
     * @param count
     * @return
     */
    public Set<String> sDistinctRandomMembers(String key, long count) {
        return stringRedisTemplate.opsForSet().distinctRandomMembers(key, count);
    }
    // ==================== Hash 常用相关操作 ==================== //
    /**
     * 【Hash】 获取存储在哈希表中指定字段的值
     * @param key
     * @param hashKey
     * @return
     */
    public Object hGet(String key, Object hashKey) {
        return stringRedisTemplate.opsForHash().get(key, hashKey);
    }
    /**
     * 【Hash】 获取所有给定字段的值
     * @param key
     * @return
     */
    public Map<Object, Object> hGetAll(String key) {
        return stringRedisTemplate.opsForHash().entries(key);
    }
    /**
     * 【Hash】 获取给定字段的值
     * @param key
     * @param hashKeys
     * @return
     */
    public List<Object> hMultiGet(String key, Collection<Object> hashKeys) {
        return stringRedisTemplate.opsForHash().multiGet(key, hashKeys);
    }
    /**
     * 【Hash】 将value设置到指定的key
     * @param key
     * @param hashKey
     * @param value
     */
    public void hPut(String key, String hashKey, String value) {
        stringRedisTemplate.opsForHash().put(key, hashKey, value);
    }
    /**
     * 【Hash】 将map设置到指定的key
     * @param key
     * @param map
     */
    public void hPutAll(String key, Map<String, String> map) {
        stringRedisTemplate.opsForHash().putAll(key, map);
    }
    /**
     * 【Hash】 仅当hashKey不存在时才设置
     * @return
     */
    public Boolean hPutIfAbsent(String key, String hashKey, String value) {
        return stringRedisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
    }
    /**
     * 【Hash】 删除一个或多个哈希表字段
     * @param key
     * @param hashKeys
     * @return
     */
    public Long hDelete(String key, Object... hashKeys) {
        return stringRedisTemplate.opsForHash().delete(key, hashKeys);
    }
    /**
     * 【Hash】 查看哈希表 key 中，指定的字段是否存在
     * @param key
     * @param hashKey
     * @return
     */
    public Boolean hExists(String key, Object hashKey) {
        return stringRedisTemplate.opsForHash().hasKey(key, hashKey);
    }
    /**
     * 【Hash】 为哈希表 key 中的指定字段的整数值加上增量 increment
     * @param key
     * @param hashKey
     * @param delta
     * @return 返回增量后的数值
     */
    public Long hIncrement(String key, Object hashKey, long delta) {
        return stringRedisTemplate.opsForHash().increment(key, hashKey, delta);
    }
    /**
     * 【Hash】 为哈希表 key 中的指定字段的整数值加上增量 increment
     * @param key
     * @param hashKey
     * @param delta
     * @return 返回增量后的数值
     */
    public Double hIncrement(String key, Object hashKey, double delta) {
        return stringRedisTemplate.opsForHash().increment(key, hashKey, delta);
    }
    /**
     * 【Hash】 获取所有哈希表中的字段
     * @param key
     * @return
     */
    public Set<Object> hKeys(String key) {
        return stringRedisTemplate.opsForHash().keys(key);
    }
    /**
     * 【Hash】 获取哈希表中字段的数量
     * @param key
     * @return
     */
    public Long hSize(String key) {
        return stringRedisTemplate.opsForHash().size(key);
    }
    /**
     * 【Hash】 获取哈希表中所有值
     * @param key
     * @return
     */
    public List<Object> hValues(String key) {
        return stringRedisTemplate.opsForHash().values(key);
    }
}